package com.woohua.thread.lockscene;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.StampedLock;

/***
 * @title StampedLockCache
 * @description
 * @author woo hua
 * @version 1.0.0
 * @create 2023/3/21 14:17
 **/
public class StampedLockCache {

    final Map<Integer, Integer> map = new HashMap<>();
    StampedLock stampedLock = new StampedLock();
    private AtomicInteger totalReadTimes = new AtomicInteger();
    private AtomicInteger totalWriteTimes = new AtomicInteger();
    private AtomicInteger conflictTimes = new AtomicInteger();

    public void put(Integer key, Integer val) {
        long stamp = stampedLock.writeLock();
        try {
            StampedLockDemo.sleep(5);   // 模拟写耗时
            totalWriteTimes.getAndIncrement();
            map.put(key, val);
        } finally {
            stampedLock.unlock(stamp);  // 必须在finally块释放
        }
    }

    public Integer get(Integer key) {
        long stamp = stampedLock.tryOptimisticRead();   // 乐观锁
        Integer val = map.get(key);
        totalReadTimes.getAndIncrement();
        if (!stampedLock.validate(stamp)) {  //  判断读的过程中是否有写操作，有则重新读取
            conflictTimes.getAndIncrement();
            try {
                stamp = stampedLock.readLock();
                val = map.get(key);
            } finally {
                stampedLock.unlockRead(stamp);  // 必须在finally 块解锁
            }
        }
        return val;
    }

    public void printTime() {
        System.out.println("Read times: " + totalReadTimes.get() + "， Writer times: " + totalWriteTimes.get() +
                "， Conflict times: " + conflictTimes.get());
    }
}
